<template>
  <div class="xhyk-table-2" ref="xhykTableDom">
    <el-table class="xhykTable2" :class="[props.tableClass]" v-bind="$attrs"
              :highlight-current-row="props.highlight"
              :row-key="idKey" :size="props.size"
              :stripe="props.stripe" :scrollbar-always-on="scrollAlways"
              :border="props.border" :data="tableData" :tree-props="treePropD"
              @cell-click="cellClickFn" @row-dblclick="rowClickDFn"
              @cell-contextmenu="cellMenuFn" @row-contextmenu="rowMenuFn"
              @header-click="headerClickFn" @header-contextmenu="headerMenuFn"
              :row-class-name="addRowClassFn" :expand-row-keys="nowExpandRowList"
              :header-cell-class-name="headerClassFn" :cell-class-name="cellClassFn"
              @select="selectChangeFn" @select-all="selectAllChangeFn"
              @row-click="rowClickFn" ref="tableDom">

      <!-- 主要key要和下面的cellClickToEmitFn一致 -->
      <el-table-column v-for="(item,index) in tableFields"
                       :key="item._fieldId"
                       v-bind="item" :label="item._labelText">

        <!-- region 头部插槽 -->
        <template #header="{column,$index}">
          <span class="tableHeader">
            <slot :name="item.labelSlot" :item="item"
                  :column="column" :$index="$index"
                  :otherQuery="props.otherQuery">
              <span class="tableHeaderText">
                <span>
                  {{
                    item._labelFn ? item._labelFn({column, $index, item, otherQuery: props.otherQuery}) :
                        getI18nTextFn(item.label, item.i18Text)
                  }}
                </span>
                <el-tooltip class="headTooltip" v-if="item.help"
                            v-bind="item.helpOptions"
                            :placement="item.helpOptions?.placement?item.helpOptions?.placement:'top'">
                <span class="labelHelpIcon">
                 <el-icon size="16"><QuestionFilled/></el-icon>
                </span>
                  <template #content>
                    <span>{{
                        typeof item.help == 'function' ? item.help({
                          column,
                          $index,
                          item,
                          otherQuery: props.otherQuery
                        }) : item.help
                      }}</span>
                  </template>
                </el-tooltip>
              </span>
            </slot>
          </span>
        </template>
        <!-- endregion -->

        <!-- region 内容插槽 -->
        <template #default="{ row, $index, column}" v-if="!(['selection','index'].includes(item.type))">
          <slot :name="item.slot" :row="row" :$index="$index" :column="column"
                :item="item" :otherQuery="props.otherQuery" v-if="item.slot"/>

          <span class="tableCell" v-else>
            <span class="callBackCell" v-if="typeof item.callBack == 'function'">
              {{ item.callBack({row, otherQuery: props.otherQuery, $index, column, item}) }}
            </span>

            <span class="htmlCell" v-else-if="typeof item.html == 'function'">
              <span v-html="item.html({row,otherQuery: props.otherQuery,$index,column,item})"></span>
            </span>

            <span class="defaultCell" v-else>
              {{ row[item.prop] }}
            </span>
          </span>
        </template>
        <!-- endregion -->

        <!-- region 筛选图标 -->
        <template #filter-icon="{filterOpened}">
          <slot name="filterIcon">
            <span class="myFilterIcon">
              <el-icon size="17"><Filter/></el-icon>
            </span>
          </slot>
        </template>
        <!-- endregion -->

      </el-table-column>
    </el-table>
  </div>
</template>

<script setup>
import {ref, watch, computed, nextTick, useAttrs, h, createApp} from 'vue'
import {
  ElTable, ElTableColumn,
  ElTooltip, ElIcon
} from 'element-plus'
import {QuestionFilled, Filter} from '@element-plus/icons-vue'
import IconX from './xhykIcon.vue'


// region 参数
const props = defineProps({
  /* 更多字段参考ElTable组件 */

  // 勾选的双向绑定（包含了当前分页，和额外分页数据）
  modelValue: {
    type: [String, Number, Object],
    default: ''
  },

  // 表格数据
  tableData: {
    type: Object,
    default: []
  },

  // 改变的字段，保存在本地
  localField: {
    type: String,
    default: undefined
  },

  // 表格字段
  tableFields: {
    type: Object,
    default: [
      // {
      //   // 字段名。字符串或函数，函数时返回字符串(注意打印excel时，如果是函数，参数只有item)
      //   label: '名称',
      //   // 绑定在数据上的字段名
      //   prop: '',
      //   // label的插槽名称，插槽参数：{column,$index,item(当前tableField),otherQuery(props.otherQuery)}
      //   labelSlot: '',
      //   // 内容单元格的插槽名称，插槽参数：{row,$index,column,item(当前tableField),otherQuery(props.otherQuery)}
      //   slot: '',
      //   // 筛选图标(只支持有xhyk-icon组件的版本)
      //   filterIcon: '',
      //   // 自定义筛选图标的插槽名称，插槽参数：{filterOpened,item(当前tableField),otherQuery(props.otherQuery)}
      //   filterSlot: '',
      //   // 内容回调方法，接受四个参数：(row: any, otherQuery: props.otherQuery, $index: number, column: any, item: 当前tableField)
      //   callback: undefined,
      //   // html回调方法，返回结果用v-html进行渲染，参数同上callback
      //   html: undefined,
      //   // 是否显示
      //   show: true,
      //   // 国际化文本，优先级：labelSlot > label函数 > i18Text > label字符串
      //   i18Text: "",
      //   // 点击单元格是否会触发点击行事件。默认true/undefined是即需要。存在slot插槽时，如果没有注明rowClick为true，则默认不触发点击事件和勾选事件
      //   rowClick: true,
      //   // 点击单元格是否会触发行勾选改变（配合props.selectChange）。存在slot插槽时同上
      //   rowSelect: true,
      //   // 单元格/行是否会触发右击事件。默认true/undefined是即需要
      //   rowMenu: true,
      //   // 是否会触发表头点击事件。默认true/undefined是即需要。存在labelSlot插槽时同上
      //   headerClick: true,
      //   // 是否会触发表头右击事件。默认true/undefined是即需要。存在labelSlot插槽时同上
      //   headerMenu: true,
      //   // 非空文本或方法（为了处理国际化）时，开启说明提示文本图标，方法参数同上labelSlot
      //   help: '',
      //   // 生成筛选数据的回调函数，接受三个参数，1、item(当前tableField)，2、data表格数据，3、otherQuery
      //   filtersCallBack: undefault,
      //   // 筛选数据的方法，undefined时默认根据item.prop字段去过滤===value值
      //   filterMethod: undefault,
      //   // ELtooltip组件的属性。
      //   helpOptions: {},
      //   /* 更多字段参考ElTableColumn组件 */
      // }
    ]
  },

  // 额外参数，用于外部的tableFields的回调处理
  otherQuery: {
    type: Object,
    default: {}
  },

  // 点击行对勾选的改变。-1：不做任何操作。0：只会取消，1：只会勾选。2：反选。3：清空其他选中，选中当前。4：清空其他选中，反选当前
  selectChange: {
    type: [Number, String],
    default: -1
  },

  // 数据的唯一key。数据出现id不是唯一，自己在外部拼接新的唯一字段名并修改该值
  rowKey: {
    type: [String, Object],
    default: 'id'
  },

  // 高亮
  highlight: {
    type: Boolean,
    default: true
  },

  // 带斑马纹的表格
  stripe: {
    type: Boolean,
    default: true
  },

  // 边线
  border: {
    type: Boolean,
    default: true
  },

  // 表格大小样式
  size: {
    type: String,
    default: 'small'
  },

  // 滚动条设置
  scrollStyle: {
    type: Object,
    default: {
      // always: true, // 可以显示滚动条时，总是显示滚动条
      // width: '14px', // 两条滚动条宽带。接受Number或string，下面值都有总体和XY区分（XY权限优先）
      // widthX: '14px',
      // widthY: '14px',
      // color: '#909399',  // 两条滚动条颜色
      // colorX: undefined,  // X滚动条颜色
      // colorY: undefined,  // Y滚动条颜色
      // opacity: 0.7, // 滚动条透明度
      // opacityX: undefined, // 滚动条透明度
      // opacityY: undefined, // 滚动条透明度
      // translate: '2px', // 偏移量
      // translateX: undefined,
      // translateY: undefined,
      // show: true, // 不写或true时，为显示两条滚动条，否则隐藏
    }
  },


  // region 树形结构配置

  // 树形结构
  treeProps: {
    type: Object,
    default: {}
  },

  // 是否为树形结构(可以不遍历子级)
  isTree: {
    type: Boolean,
    default: true
  },

  // 父级勾选是否影响子级
  noClick: {
    type: Boolean,
    default: false
  },

  // 树形结构图标
  treeIcon: {
    type: String,
    default: 'CaretRight'
  },

  // endregion

  // 类名
  tableClass: {
    type: String,
    default: 'vxeTableClass'
  },

  // 列当前选中时的类名
  nowColumnClass: {
    type: String,
    default: 'now_column'
  },

  // 行当前选中时的类名
  nowRowClass: {
    type: String,
    default: 'nowRowClass'
  },

})

const emit = defineEmits([
  // 双向绑定勾选数据，单元格被点击
  'update:modelValue', 'cellClick',
  // 行单击，行双击
  'rowClick', 'rowClickD',
  // 行右击，单元格右击
  'rowMenu', 'cellMenu',
  // 行勾选。{row全部勾选时为undefined，list当前勾选列表(注意这个只统计当前分页)，toChange真为勾选假为取消}
  'select',
  // 表头单击，表头右击
  'headerClick', 'headerMenu'])

const $attrsObj = useAttrs()

// 获取属性对应值或方法。如果property为方法时，不需要传on前缀。
const getAttrFn = (property = '') => {
  let nowKey = ''
  const newFind = property.toLowerCase().replaceAll('-', '')
  for (let key in $attrsObj) {
    const tempKey = key.toLowerCase().replaceAll('-', '')
    // 查找属性或事件
    if (tempKey == newFind || tempKey == `on${newFind}`) {
      nowKey = key
      break
    }
  }
  if (nowKey) {
    return $attrsObj[nowKey]
  }
}

function getMid(len = 30) {
  let result = Date.now().toString();
  while (result.length < len) {
    let temp = Math.random().toString(36)
    if (temp.length > 2) {
      temp = temp.slice(2, temp.length)
    } else {
      temp = "xhyk"
    }
    result = `${temp}${result}`
  }

  if (result.length > len) {
    let index = result.length - len
    result = result.slice(index, result.length)
  }

  return result
}

// endregion


// region 工具函数

// 字符串/数值转px像素。接受[String,Number]的style样式尺寸
function getPx(text, defaultPx = 'px') {
  let tempList = ['px', 'rpx', 'vw', 'vh', '%', 'em', 'auto']
  if (typeof text == 'string') {
    const havePx = tempList.find(row => text.includes(row))
    if (havePx) {
      return text
    } else {
      return `${parseFloat(text)}${defaultPx}`
    }
  } else if (typeof text == 'number') {
    let temp = parseFloat(text)
    return `${temp}${defaultPx}`
  }
  return text
}

// 遍历嵌套取值。根据children字段遍历下级列表。返回当前子级对象
async function findChildren(data = [], callBack = undefined, children = "children") {
  let tempResult = undefined
  const findFn = async (ChildData, father) => {
    let isOk = false
    for (let item of ChildData) {
      if (typeof callBack == "function") {
        const isBreak = await callBack(item, father)
        if (isBreak == true) {
          tempResult = item
          isOk = true
          break;
        }
      }
      if (isOk) {
        tempResult = item
        return item
      }

      // 如果有下一级数据
      if (item[children] != undefined && item[children].length > 0) {
        let result = await findFn(item[children], item)
        if (result) {
          return true
        }
      }
    }
    return isOk;
  }
  await findFn(data, {})
  return tempResult
}

// endregion


// region elTable对象

const tableDom = ref({})

const xhykTableDom = ref({})

// endregion


// region 树形结构

// 树形结构配置
const treePropD = computed(() => {
  const result = {
    children: props.treeProps.children || 'children',
    hasChildren: props.treeProps.hasChildren || 'hasChildren',
    checkStrictly: props.treeProps.checkStrictly || props.noClick,
  }
  for (let key in props.treeProps) {
    result[key] = props.treeProps[key]
  }
  return result
})


// region 自定义树形结构图标
const addMyExpandIcon = (data) => {
  nextTick(() => {
    if (props.treeIcon) {
      // 找到这个单元格
      const cellList = xhykTableDom.value.querySelectorAll(`table.el-table__body tbody .el-table__expand-icon`)
      cellList.forEach(cell => {
        if (cell.children?.length == 1) {
          if (props.treeIcon && !cell.children[0].className.includes('myExpandIcon')) {
            // 重新挂载自己的元素
            const app = createApp({
              render() {
                return h(IconX, {
                  type: props.treeIcon,
                  size: 15,
                  style: {
                    transform: 'translateY(4px)',
                    // width: '14px',
                    // height: '14px',
                  },
                  class: 'xhAll myExpandIcon'
                });
              }
            })
            app.mount(cell)
          }
        }
      })
    }
  })

}
// endregion

// endregion

// region 处理国际化

const getI18nTextFn = (oldText, i18nText) => {
  if (typeof window.$t == 'function' && i18nText) {
    return window.$t(i18nText)
  } else {
    return oldText
  }
}

// endregion


// region 表格字段

// 当前的表格字段
const tableFields = ref([])

// 设置表格
const setFieldFn = () => {
  tableFields.value = []
  props.tableFields?.forEach((item, index) => {

    item._fieldId = `_${item._labelText}_${item.prop}_${item.slot}_${item.labelSlot}`

    item.align = item.align == undefined ? 'center' : item.align

    // 如何是方法，则赋值给_labelFn，则原来的label改成字符串
    item._labelFn = typeof item.label == 'function' ? item.label : undefined
    item._labelText = typeof item.label == 'string' ? item.label : (item.i18Text || '')

    // region 筛选

    // 弹窗位置
    item.filterPlacement = item.filterPlacement == undefined ? 'bottom' : item.filterPlacement

    if (typeof item.filterCallBack == 'function') {
      item.filters = item.filters || []
    }
    if (item.filters?.length >= 0 && item.filterMethod == undefined) {
      item.filterMethod = (value, row, column) => {
        return row[item.prop] === value
      }
    }

    // endregion

    if (item.width != undefined) {
      item.width = getPx(item.width)
    }

    if (item.minWidth != undefined) {
      item.minWidth = getPx(item.minWidth)
    }

    if (typeof item.fixed != 'string') {
      item.fixed = undefined
    }

    if (item.show != false) {
      tableFields.value.push(item)
    }
  })

  if (props.localField) {
    localStorage.setItem(props.localField, JSON.stringify(tableFields.value))
  }
}

watch(() => props.tableFields, (newV, oldV) => {
  setFieldFn()
}, {immediate: true, deep: true})

// endregion


// region 筛选当前数据显示

// 设置默认筛选数据
const setFilterTableDataFn = async () => {
  for (let i = 0; i < tableFields.value.length; i++) {
    const item = tableFields.value[i]
    if (typeof item.filterCallBack == 'function') {
      const result = await item.filterCallBack({
        item,
        data: tableData.value,
        otherQuery: props.otherQuery
      })
      item.filters = result || []
    }
  }
}

// endregion


// region 表格唯一值

const idKey = 'xhykTableV3Key'

// 给数据设置key对应的值
const setKeyValue = (item = {}) => {
  if (item[idKey]) {
    return item[idKey]
  }
  let idList = []
  if (typeof props.rowKey == 'string') {
    idList = [props.rowKey]
  } else if (props.rowKey instanceof Array) {
    // ['id','code'] => `${id}_${code}`
    idList = props.rowKey
  }
  let idValue = ""
  if (props.rowKey == undefined) {
    idValue = getMid(30)
  } else {
    idList.forEach(key => {
      idValue = `${idValue}_${item[key]}`
    })
  }
  item[idKey] = idValue
  return idValue
}
// endregion


// region 表格数据

// 当前的表格数据
const tableData = ref([])

// 当前数据的一层数据（树形结构转为一层）
let levelData = []

// 当前勾选数据（包含了当前分页，和额外分页数据）
const nowSelect = ref([])

// 是否开启改变选中数据
const updateSelect = ref(false)

// 回显当前选中数据
const showSelectFn = (oldCheckList) => {
  nextTick(() => {
    if (oldCheckList?.length > 0) {
      oldCheckList.forEach(item => {
        setKeyValue(item)
        // 找到这个数据
        const thisData = levelData.find(row => row[idKey] == item[idKey])
        if (thisData) {
          tableDom.value.toggleRowSelection(thisData, false)
        }
      })
    }

    if (props.modelValue?.length > 0) {
      nowSelect.value = props.modelValue
      const isLong = levelData.length > nowSelect.value
      if (isLong) {
        // 数据比勾选的多
        nowSelect.value.forEach(item => {
          setKeyValue(item)
          const thisData = levelData.find(row => row[idKey] == item[idKey])
          if (thisData) {
            // 同步表格数据
            for (let key in thisData) {
              item[key] = thisData[key]
            }
            tableDom.value.toggleRowSelection(thisData, true)
          }
        })
      } else {
        // 勾选的比数据多
        levelData.forEach(item => {
          const thisData = nowSelect.value.find(row => {
            setKeyValue(row)
            return row[idKey] == item[idKey]
          })
          if (thisData) {
            // 同步表格数据
            for (let key in item) {
              thisData[key] = item[key]
            }
            tableDom.value.toggleRowSelection(item, true)
          }
        })
      }

    } else {
      tableDom.value && tableDom.value.clearSelection && tableDom.value.clearSelection()
      nowSelect.value = []
    }
    setFilterTableDataFn()
    updateSelect.value = true
  })
}


watch(() => props.tableData, async (newV, oldV) => {
  nextTick(async () => {
    const tempList = newV || []
    updateSelect.value = false
    levelData = []
    if (tempList.length > 0) {
      // 树形结构转为一层结构
      if (props.isTree) {
        await findChildren(tempList, (item, father) => {
          levelData.push(item)
          setKeyValue(item)
        }, treePropD.value.children || 'children')
      } else {
        tempList.forEach(row => setKeyValue(row))
        for (let i = 0; i < tempList.length; i++) {
          const item = tempList[i]
          setKeyValue(item)
          levelData.push(item)
        }
      }
      tableData.value = newV || []
    } else {
      tableData.value = []
    }
    showSelectFn()
  })
}, {immediate: true})


let timeId = 0
let outTimeId = 0
watch(() => props.modelValue, (newV, oldV) => {
  clearInterval(timeId)
  clearTimeout(outTimeId)
  if (updateSelect.value) {
    showSelectFn(oldV)
  } else {
    outTimeId = setTimeout(() => {
      clearInterval(timeId)
    }, 2000)
    timeId = setInterval(() => {
      if (updateSelect.value) {
        showSelectFn(oldV)
      }
    }, 500)
  }
}, {deep: true})

// endregion


// region 当前选中的行/列。行列类名


const nowColumn = ref({})

const nowRow = ref({
  // tableData的当前行数据
  row: {},
  // 当单元格所在列
  column: {},
  // 事件
  event: {}
})

const headerClassFn = ({row, column, rowIndex, columnIndex}) => {
  const result = []

  if (column.id == nowColumn.value.id) {
    if (props.nowColumnClass) {
      result.push(props.nowColumnClass)
    }
  }
  const headerClass = getAttrFn('header-cell-class-name')
  let queryName = ''
  if (typeof headerClass == 'function') {
    queryName = headerClass({row, column, rowIndex, columnIndex}, props.otherQuery)
  } else {
    queryName = headerClass
  }
  if (queryName) {
    result.push(queryName)
  }

  return result.join(' ')
}

// 行添加类名。注意不能用async
const addRowClassFn = (data) => {
  const queryRowClassName = getAttrFn('rowClassName')
  let queryName = ''
  if (typeof queryRowClassName == 'function') {
    queryName = queryRowClassName(data, props.otherQuery)
  } else {
    queryName = queryRowClassName
  }
  let result = `${queryName || ''}`
  if (nowRow.value.row[idKey] != undefined && nowRow.value.row[idKey] == data.row[idKey]) {
    let checkName = props.nowRowClass
    if (typeof props.nowRowClass == 'object') {
      checkName = props.nowRowClass.join(' ')
    }
    if (props.highlight) {
      result = `${result} ${checkName}`
    }
  }
  return result
}

const cellClassFn = ({row, column, rowIndex, columnIndex}) => {
  const result = []
  if (column.id == nowColumn.value.id) {
    if (props.nowColumnClass) {
      result.push(props.nowColumnClass)
    }
  }

  const cellClass = getAttrFn('cell-class-name')
  let queryName = ''
  if (typeof cellClass == 'function') {
    queryName = cellClass({row, column, rowIndex, columnIndex}, props.otherQuery)
  } else {
    queryName = cellClass
  }
  if (queryName) {
    result.push(queryName)
  }

  addMyExpandIcon({row, column, rowIndex, columnIndex})
  return result.join(' ')
}

// endregion

// region 点击事件

// 判断插槽是否允许触发点击事件和勾选事件
const cellClickToEmitFn = (column) => {
  const result = {
    canClick: true,
    canSelect: true,
    canMenu: true,
    headerClick: true,
    headerMenu: true,
  }
  if (column == undefined) {
    return result
  }
  const rawColumnKey = column.rawColumnKey
  const thisField = tableFields.value.find(item => {
    const thisRawColumnKey = item._fieldId
    return thisRawColumnKey == rawColumnKey
  })
  if (thisField) {
    result.canClick = thisField.rowClick != false ? true : false
    result.canSelect = thisField.rowSelect != false ? true : false
    result.canMenu = thisField.rowMenu != false ? true : false
    result.headerClick = thisField.headerClick != false ? true : false
    result.headerMenu = thisField.headerMenu != false ? true : false

    // 插槽时，如果没有注明rowClick为true，则默认不触发点击事件和勾选事件
    if (thisField.slot) {
      result.canClick = thisField.rowClick != true ? false : true
      result.canSelect = thisField.rowSelect != true ? false : true
    }

    if (thisField.labelSlot) {
      result.headerClick = thisField.headerClick != true ? false : true
      result.headerMenu = thisField.headerMenu != true ? false : true
    }

  }

  return result
}

// 单元格点击事件
const cellClickFn = (row, column, cell, event) => {
  const canChange = cellClickToEmitFn(column)
  if (canChange.canSelect) {
    changeSelectFn(row, props.selectChange, true)
  }
  if (canChange.canClick) {
    emit('cellClick', {row, column, cell, event})
  }
}

// 行单点击事件
const rowClickFn = (row, column, event) => {
  nowRow.value = {
    row,
    column,
    event
  }
  const canChange = cellClickToEmitFn(column)
  if (canChange.canSelect) {
    changeSelectFn(row, props.selectChange, true)
  }
  if (canChange.canClick) {
    emit('rowClick', {row, column, event})
  }
}

// 行双击事件
const rowClickDFn = (row, column, event) => {
  nowRow.value = {
    row,
    column,
    event
  }
  const canChange = cellClickToEmitFn(column)
  if (canChange.canSelect) {
    changeSelectFn(row, props.selectChange, true)
  }
  if (canChange.canClick) {
    emit('rowClickD', {row, column, event})
  }
}

// 行右击事件
const rowMenuFn = (row, column, event) => {
  const canChange = cellClickToEmitFn(column)
  if (canChange.canMenu) {
    emit('rowMenu', {row, column, event})
  } else {
    event.preventDefault()
  }
}

// 单元格右击事件
const cellMenuFn = (row, column, cell, event) => {
  const canChange = cellClickToEmitFn(column)
  if (canChange.canMenu) {
    emit('cellMenu', {row, column, cell, event})
  } else {
    event.preventDefault()
  }
}

// 表头点击事件
const headerClickFn = (column, event) => {
  nowColumn.value = column
  const canChange = cellClickToEmitFn(column)
  if (canChange.headerClick) {
    emit('headerClick', {column, event})
  }
}

// 表头右击事件
const headerMenuFn = (column, event) => {
  const canChange = cellClickToEmitFn(column)
  if (canChange.headerMenu) {
    emit('headerMenu', {column, event})
  }
}

// endregion


// region 勾选事件

// 改变勾选事件。type -1：不做任何操作。0：只会取消，1：只会勾选。2：反选。3：清空其他选中，选中当前。4：清空其他选中，反选当前。
// toEmitSelect：去触发勾选事件。needModel：是否更新双向绑定
const changeSelectFn = (rowOrKeyValue, type = 2, toEmitSelect = true, needModel = true) => {
  let thisType = parseInt(type)
  if (thisType == -1) {
    return;
  }

  let toChoose = false
  let thisItem = rowOrKeyValue

  const nowSelectList = tableDom.value.getSelectionRows()
  nextTick(() => {
    switch (thisType) {
      case 0:
        tableDom.value.toggleRowSelection(thisItem, false)
        break
      case 1:
        tableDom.value.toggleRowSelection(thisItem, true)
        toChoose = true
        break;
      case 2:
        const haveChoose2 = nowSelectList.find(item => item[idKey] == thisItem[idKey])
        toChoose = haveChoose2 ? false : true
        tableDom.value.toggleRowSelection(thisItem, toChoose)
        break;
      case 3:
        nowSelectList.find(item => tableDom.value.toggleRowSelection(item, false))
        tableDom.value.toggleRowSelection(thisItem, true)
        toChoose = true
        break;
      case 4:
        const haveChoose4 = nowSelectList.find(item => item[idKey] == thisItem[idKey])
        nowSelectList.find(item => tableDom.value.toggleRowSelection(item, false))
        toChoose = haveChoose4 ? false : true
        tableDom.value.toggleRowSelection(thisItem, toChoose)
        break;

    }

    const nowList = tableDom.value.getSelectionRows()
    if (needModel) {
      // 过滤掉当前分页数据
      const tempData = nowSelect.value.filter(item => {
        const isData = levelData.find(row => row[idKey] == item[idKey])
        if (isData) {
          return false
        }
        return true
      })

      // 添加当页的勾选
      tempData.push(...nowList)
      nowSelect.value = tempData
      emit('update:modelValue', tempData)
    }

    if (toEmitSelect) {
      emit('select', {
        list: nowList,
        row: thisItem,
        toChoose: toChoose,
      })
    }

  })

}

// 勾选事件
const selectChangeFn = (list, row) => {
  const have = list.find(item => item[idKey] == row[idKey])
  if (have) {
    nowSelect.value.push(row)
  } else {
    nowSelect.value = nowSelect.value.filter(item => item[idKey] != row[idKey])
  }
  emit('update:modelValue', nowSelect.value)
  emit('select', {
    list: list,
    row: row,
    toChoose: have ? true : false,
  })
}

// 全部勾选事件
const selectAllChangeFn = (list) => {
  if (list.length > 0) {
    // 添加当前分页中的数据
    list.forEach(item => {
      const havePush = nowSelect.value.find(row => row[idKey] == item[idKey])
      if (!havePush) {
        nowSelect.value.push(item)
      }
    })
  } else {
    // 去掉当前分页中的数据
    nowSelect.value = nowSelect.value.filter(item => {
      const have = levelData.find(row => row[idKey] == item[idKey])
      return have ? false : true
    })

  }

  emit('update:modelValue', nowSelect.value)
  emit('select', {
    list: list,
    row: undefined,
    toChoose: list.length == 0,
  })
}

// endregion


// region 展开事件

// 当前折叠
const nowExpandRowList = ref([])

const setExpand = (rowList = [], expand = true) => {
  if (expand) {
    rowList.forEach(item => {
      const havePush = nowExpandRowList.value.find(row => row == item[idKey])
      if (!havePush) {
        nowExpandRowList.value.push(item[idKey])
      }
    })
  } else {
    nowExpandRowList.value = nowExpandRowList.value.filter(item => {
      const have = rowList.find(row => row[idKey] == item)
      if (have) {
        return false
      }
      return true
    })
  }
}

const setExpandAll = (expand = true) => {
  if (expand) {
    levelData.forEach(item => {
      const havePush = nowExpandRowList.value.find(row => row == item[idKey])
      if (!havePush) {
        nowExpandRowList.value.push(item[idKey])
      }
    })
  } else {
    nowExpandRowList.value = []
  }
}

// endregion


// region 滚动条

// 总是显示
const scrollAlways = ref(false)
const widthX = ref('14px')
const widthY = ref('14px')
const colorX = ref('#909399')
const colorY = ref('#909399')
const opacityX = ref(0.7)
const opacityY = ref(0.7)
const translateX = ref('2px')
const translateY = ref('2px')
const showX = ref(true)
const showY = ref(true)
watch(() => props.scrollStyle, (newV, oldV) => {
  // region 宽度
  let width = newV.width == undefined ? '10px' : newV.width;
  widthX.value = getPx(width)
  widthY.value = getPx(width)
  if (newV.widthX != undefined) {
    widthX.value = getPx(newV.widthX)
  }
  if (newV.widthY != undefined) {
    widthY.value = getPx(newV.widthY)
  }
  // endregion

  // region 偏移量
  let translate = newV.translate == undefined ? '3px' : newV.translate;
  translateX.value = getPx(translate)
  translateY.value = getPx(translate)
  if (newV.translateX != undefined) {
    translateX.value = getPx(newV.translateX)
  }
  if (newV.translateY != undefined) {
    translateY.value = getPx(newV.translateY)
  }

  // endregion

  // region 颜色
  let color = newV.color == undefined ? '#909399' : newV.color
  colorX.value = color
  colorY.value = color
  if (newV.colorX != undefined) {
    colorX.value = newV.colorX
  }
  if (newV.colorY != undefined) {
    colorY.value = newV.colorY
  }
  // endregion

  // region 透明度
  let opacity = newV.opacity == undefined ? 0.7 : newV.opacity
  opacityX.value = opacity
  opacityY.value = opacity
  if (newV.opacityX != undefined) {
    opacityX.value = newV.opacityX
  }
  if (newV.opacityY != undefined) {
    opacityY.value = newV.opacityY
  }
  // endregion

  // region 显示
  let show = (newV.show == undefined || newV.show == true) ? 'block' : 'none'
  showX.value = show
  showY.value = show
  if (newV.showX != undefined) {
    showX.value = (newV.showX == undefined || newV.showX == true) ? 'block' : 'none'
  }
  if (newV.showY != undefined) {
    showY.value = (newV.showY == undefined || newV.showY == true) ? 'block' : 'none'
  }
  // endregion

  // region 总是显示
  scrollAlways.value = (newV.always == undefined || newV.always == true) ? true : newV.always
  // endregion


}, {immediate: true, deep: true})

// endregion


// region 打印方法

const printFn = () => {
  // 创建一个临时的 iframe 来承载打印内容
  const iframe = document.createElement('iframe');
  iframe.style.position = 'absolute';
  iframe.style.top = '0px';
  iframe.style.left = '0px';
  iframe.style.right = '0px';
  iframe.style.bottom = '0px';
  iframe.style.bottom = '0px';
  iframe.style.opacity = 0;
  document.body.appendChild(iframe);

  const iframeDoc = iframe.contentWindow.document;

  // 获取所有样式
  const allStyles = Array.from(document.styleSheets)
      .map(sheet => {
        try {
          return Array.from(sheet.cssRules)
              .map(rule => rule.cssText)
              .join('\n');
        } catch (e) {
          return '';
        }
      })
      .join('\n');

  iframeDoc.open();
  iframeDoc.write(`<html>
          <head>
            <style>
               ${allStyles}
            </style>
          </head>
          <body>
            ${xhykTableDom.value.outerHTML}
          </body>
        </html>
      `);
  iframeDoc.close();


  iframe.contentWindow.addEventListener('afterprint', () => {
    document.body.removeChild(iframe);
  });

  // 等待 iframe 加载完成
  iframe.onload = () => {
    iframe.contentWindow.focus();
    iframe.contentWindow.print();
  }
}

// endregion


// region 暴露对象
defineExpose({
  idKey,
  tableDom,
  tableData,
  tableFields,
  setExpand,
  setExpandAll,
  print: printFn,
})
// endregion

</script>

<style scoped lang='scss'>
.xhyk-table-2 {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;

  .xhykTable2 {
    width: 100%;
    height: 100%;
  }
}

// region 提示弹窗
.tableHeaderText {
  display: inline-flex;
  align-items: center;

  .labelHelpIcon {
    margin-left: 4px;
    display: flex;
    align-items: center;
    cursor: help;
    color: var(--menuSysColor, #409EFF);
  }
}

// endregion

// region 滚动条
:deep(.xhykTable2) {
  .el-table__body-wrapper {

    // region 横向滚动条
    .is-horizontal {
      //bottom: calc( - 2px);
      bottom: v-bind(widthX);
      transform: translateY(v-bind(translateX));

      .el-scrollbar__thumb {
        height: v-bind(widthX) !important;
        background-color: v-bind(colorX);
        opacity: v-bind(opacityX);
        display: v-bind(showX);
      }
    }

    // endregion

    // region 纵向滚动条
    .is-vertical {
      //right: calc($scrollW - 2px);
      right: v-bind(widthY);
      transform: translateX(v-bind(translateY));
      z-index: 50;

      .el-scrollbar__thumb {
        width: v-bind(widthY) !important;
        background-color: v-bind(colorY);
        opacity: v-bind(opacityY);
        display: v-bind(showY);
      }
    }

    // endregion

  }
}

// endregion


// region 仿vxeTable样式
.vxeTableClass {

  :deep(.el-table__cell) {
    border-bottom: 1px solid #ccc;
    border-right: 1px solid #ccc !important;
  }

  // region 头部样式
  :deep(.el-table__header) {
    .el-table__cell {
      background-color: #F0F0F0;
      border-top: 1px solid #B1B3B7 !important;
      border-bottom: 1px solid #B1B3B7 !important;
    }
  }

  // endregion

}

// endregion


// region 选中行/列样式
$cv: #E2EDF8;

// region 当前选中列样式

.xhykTable2 {
  :deep(.now_column.el-table__cell) {
    background-color: $cv !important;
    border-bottom: 1px solid #B1B3B7 !important;
    border-right: 1px solid var(--menuSysColor, black) !important;
    border-left: 1px solid var(--menuSysColor, black) !important;
  }
}

// endregion

// region 当前选中行。

.xhykTable2 {
  :deep(.nowRowClass) {
    td.el-table__cell {
      background-color: $cv !important;
      color: var(--menuSysColor, #606266) !important;
      border-bottom: 1px solid #B1B3B7 !important;
      border-top: 1px solid var(--menuSysColor, black) !important;
      border-bottom: 1px solid var(--menuSysColor, black) !important;
    }
  }
}

// endregion

// endregion


// region 筛选图标
:deep(.el-table__column-filter-trigger) {
  margin-left: 4px;
}

// endregion


// region 暂无数据进行居中
.xhyk-table-2 {
  :deep(.el-scrollbar__wrap) {
    display: flex;

    .el-table__empty-text {
      font-size: 16px;
    }
  }
}

// endregion
</style>